#!/usr/bin/env pwsh

# 健康检查脚本 - 一键体检端口/路由/转发/SSE/数据库
# 适用于AI Chat项目

Write-Host "=================================================="
Write-Host "AI Chat 项目健康检查脚本"
Write-Host "=================================================="

# 配置变量
$backendPort = 8001
$frontendPort = 5173
$postgresPort = 5432
$ollamaPort = 11434
$backendBaseUrl = "http://localhost:$backendPort"
$apiBaseUrl = "http://localhost:$backendPort/v1"

# 检查结果统计
$totalTests = 0
$passedTests = 0
$failedTests = 0

function Write-Result($status, $message) {
    if ($status -eq "PASS") {
        Write-Host "✅ [$status] $message" -ForegroundColor Green
    } elseif ($status -eq "FAIL") {
        Write-Host "❌ [$status] $message" -ForegroundColor Red
    } else {
        Write-Host "ℹ️ [$status] $message" -ForegroundColor Yellow
    }
}

function Test-Port($port, $description) {
    $global:totalTests++
    try {
        $listener = [System.Net.Sockets.TcpListener]::new("127.0.0.1", $port)
        try {
            $listener.Start()
            Write-Result "FAIL" "端口 $port ($description) 未被占用，服务可能未启动"
            $global:failedTests++
            return $false
        } catch [System.Net.Sockets.SocketException] {
            Write-Result "PASS" "端口 $port ($description) 已被占用，服务正在运行"
            $global:passedTests++
            return $true
        } finally {
            $listener.Stop()
        }
    } catch {
        Write-Result "FAIL" "端口检查 $port ($description) 失败: $_"
        $global:failedTests++
        return $false
    }
}

function Test-HttpEndpoint($url, $description, $expectedStatus = 200) {
    $global:totalTests++
    try {
        $response = Invoke-WebRequest -Uri $url -Method GET -TimeoutSec 5 -UseBasicParsing
        if ($response.StatusCode -eq $expectedStatus) {
            Write-Result "PASS" "HTTP端点 $description 可访问: $url"
            $global:passedTests++
            return $true
        } else {
            Write-Result "FAIL" "HTTP端点 $description 返回状态码 $($response.StatusCode)，预期 $expectedStatus: $url"
            $global:failedTests++
            return $false
        }
    } catch {
        Write-Result "FAIL" "HTTP端点 $description 访问失败: $url - $_"
        $global:failedTests++
        return $false
    }
}

function Test-SSEEndpoint() {
    $global:totalTests++
    $url = "$apiBaseUrl/chat/stream"
    $testData = @{
        "messages" = @(
            @{
                "role" = "user"
                "content" = "hello"
            }
        )
        "stream" = $true
    } | ConvertTo-Json
    
    try {
        Write-Host "测试SSE流式端点..." -ForegroundColor Cyan
        $request = [System.Net.HttpWebRequest]::Create($url)
        $request.Method = "POST"
        $request.ContentType = "application/json"
        $request.Timeout = 10000 # 10秒超时
        
        # 写入请求体
        $bytes = [System.Text.Encoding]::UTF8.GetBytes($testData)
        $request.ContentLength = $bytes.Length
        $stream = $request.GetRequestStream()
        $stream.Write($bytes, 0, $bytes.Length)
        $stream.Close()
        
        # 获取响应
        $response = $request.GetResponse()
        $contentType = $response.ContentType
        
        if ($contentType -like "*text/event-stream*" -or $response.StatusCode -eq 200) {
            Write-Result "PASS" "SSE流式端点响应正常: $url"
            $global:passedTests++
            $response.Close()
            return $true
        } else {
            Write-Result "FAIL" "SSE流式端点返回错误的Content-Type: $contentType"
            $global:failedTests++
            $response.Close()
            return $false
        }
    } catch {
        Write-Result "FAIL" "SSE流式端点测试失败: $url - $_"
        $global:failedTests++
        return $false
    }
}

function Test-OllamaForwarding() {
    $global:totalTests++
    $url = "$apiBaseUrl/llm/ollama/models"
    
    try {
        Write-Host "测试Ollama模型转发..." -ForegroundColor Cyan
        $response = Invoke-WebRequest -Uri $url -Method GET -TimeoutSec 10 -UseBasicParsing
        
        if ($response.StatusCode -eq 200) {
            # 检查是否返回了有效的JSON数据
            try {
                $json = $response.Content | ConvertFrom-Json
                if ($json -and ($json | Get-Member -Name "models")) {
                    Write-Result "PASS" "Ollama模型转发正常，返回模型列表: $url"
                    $global:passedTests++
                    return $true
                } else {
                    Write-Result "FAIL" "Ollama模型转发返回数据格式错误"
                    $global:failedTests++
                    return $false
                }
            } catch {
                Write-Result "FAIL" "Ollama模型转发返回无效JSON: $_"
                $global:failedTests++
                return $false
            }
        } else {
            Write-Result "FAIL" "Ollama模型转发返回状态码 $($response.StatusCode)"
            $global:failedTests++
            return $false
        }
    } catch {
        Write-Result "FAIL" "Ollama模型转发测试失败: $url - $_"
        $global:failedTests++
        return $false
    }
}

function Test-DatabaseAccess() {
    $global:totalTests++
    $url = "$apiBaseUrl/health"
    
    try {
        Write-Host "测试数据库连接..." -ForegroundColor Cyan
        $response = Invoke-WebRequest -Uri $url -Method GET -TimeoutSec 10 -UseBasicParsing
        
        if ($response.StatusCode -eq 200) {
            try {
                $json = $response.Content | ConvertFrom-Json
                if ($json -and $json.database_status -eq "connected") {
                    Write-Result "PASS" "数据库连接正常: $($json.database_type)"
                    $global:passedTests++
                    return $true
                } else {
                    Write-Result "FAIL" "数据库连接失败: $($json.database_status)"
                    $global:failedTests++
                    return $false
                }
            } catch {
                Write-Result "FAIL" "健康检查返回无效JSON: $_"
                $global:failedTests++
                return $false
            }
        } else {
            Write-Result "FAIL" "健康检查返回状态码 $($response.StatusCode)"
            $global:failedTests++
            return $false
        }
    } catch {
        Write-Result "FAIL" "数据库连接测试失败: $_"
        $global:failedTests++
        return $false
    }
}

function Test-FileAnalysisAPI() {
    $global:totalTests++
    $url = "$apiBaseUrl/files/analyze"
    
    try {
        # 创建一个简单的文本文件用于测试
        $testContent = "这是一个测试文件内容"
        $tempFile = [System.IO.Path]::GetTempFileName()
        Set-Content -Path $tempFile -Value $testContent
        
        Write-Host "测试文件分析API..." -ForegroundColor Cyan
        $response = Invoke-WebRequest -Uri $url -Method POST -TimeoutSec 10 -UseBasicParsing -ContentType "multipart/form-data" -Form @{
            "file" = Get-Item $tempFile
        }
        
        Remove-Item $tempFile -Force
        
        if ($response.StatusCode -eq 200 -or $response.StatusCode -eq 422) { # 422表示请求已接收但可能需要更多信息
            Write-Result "PASS" "文件分析API响应正常: $url"
            $global:passedTests++
            return $true
        } else {
            Write-Result "FAIL" "文件分析API返回状态码 $($response.StatusCode)"
            $global:failedTests++
            return $false
        }
    } catch {
        Write-Result "FAIL" "文件分析API测试失败: $_"
        $global:failedTests++
        return $false
    }
}

function Test-KBIngestAPI() {
    $global:totalTests++
    $url = "$apiBaseUrl/kb/ingest"
    
    try {
        # 测试API是否可以访问
        $headers = @{
            "Content-Type" = "application/json"
        }
        $testData = @{
            "documents" = @()
            "collection" = "test"
        } | ConvertTo-Json
        
        Write-Host "测试知识库入库API..." -ForegroundColor Cyan
        $response = Invoke-WebRequest -Uri $url -Method POST -TimeoutSec 10 -UseBasicParsing -Headers $headers -Body $testData
        
        if ($response.StatusCode -eq 200 -or $response.StatusCode -eq 400) { # 400表示请求格式正确但内容无效
            Write-Result "PASS" "知识库入库API响应正常: $url"
            $global:passedTests++
            return $true
        } else {
            Write-Result "FAIL" "知识库入库API返回状态码 $($response.StatusCode)"
            $global:failedTests++
            return $false
        }
    } catch {
        Write-Result "FAIL" "知识库入库API测试失败: $_"
        $global:failedTests++
        return $false
    }
}

# 开始检查
Write-Host "\n[1/3] 端口状态检查" -ForegroundColor Yellow
Test-Port $backendPort "后端服务"
Test-Port $frontendPort "前端服务"
Test-Port $postgresPort "PostgreSQL数据库"
Test-Port $ollamaPort "Ollama服务"

Write-Host "\n[2/3] API端点检查" -ForegroundColor Yellow
Test-HttpEndpoint "$apiBaseUrl/health" "健康检查端点"
Test-HttpEndpoint "$backendBaseUrl" "后端根路径"

Write-Host "\n[3/3] 功能测试" -ForegroundColor Yellow
Test-OllamaForwarding
Test-SSEEndpoint
Test-DatabaseAccess
Test-FileAnalysisAPI
Test-KBIngestAPI

# 显示总结
Write-Host "\n=================================================="
Write-Host "健康检查总结:"
Write-Host "总测试项: $totalTests"
Write-Host "通过: $passedTests"
Write-Host "失败: $failedTests"

if ($failedTests -eq 0) {
    Write-Host "🎉 所有测试通过! 系统运行正常." -ForegroundColor Green
} else {
    $passRate = [math]::Round(($passedTests / $totalTests) * 100, 2)
    Write-Host "⚠️  测试通过率: $passRate%" -ForegroundColor Yellow
    Write-Host "\n问题排查建议:"
    Write-Host "1. 检查各服务是否已启动: 后端、前端、PostgreSQL、Ollama"
    Write-Host "2. 确认配置文件中的端口和地址设置正确"
    Write-Host "3. 查看服务日志获取详细错误信息"
    Write-Host "4. 对于Ollama问题，确认模型是否已下载"
    Write-Host "5. 对于数据库问题，确认数据库服务状态和连接参数"
}
Write-Host "=================================================="